Use case: External trigger synchro

This example shows how to synchronize TIM peripherals in cascade mode with an external trigger. In this example three timers are used:

  • TIM1 is slave for an external trigger and master for TIM2.

  • TIM2 is slave for TIM1.

HAL1

HAL2

Initialize and configure timers

  • After initialization and basic configuration for TIMx, configure TIMx as master or slave timer using the following functions:

    • HAL_TIM_SlaveConfigSynchro to configure slave mode.

    • HAL_TIMEx_MasterConfigSynchronization to configure master mode.

    • HAL_TIM_OC_ConfigChannel to configure the output channel.

Start timers

  • HAL_TIM_IC_Start(&htim1, TIM_CHANNEL_2) is used to capture the external trigger.

  • HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_1) is used as trigger output for TIM2.

  • HAL_TIM_OC_Start(&htim2, TIM_CHANNEL_1) is used to generate a signal.

Initialize and configure timers

Start timers

  • HAL_TIM_IC_StartChannel(&htim1, HAL_TIM_CHANNEL_2) is used to capture the external trigger.

  • HAL_TIM_OC_StartChannel(&htim1, HAL_TIM_CHANNEL_1) is used as trigger output for TIM2.

  • HAL_TIM_OC_StartChannel(&htim2, HAL_TIM_CHANNEL_1) is used to generate a signal.

  • HAL_TIM_Start(&htim1) is used to start TIM1.

  • HAL_TIM_Start(&htim2) is used to start TIM2.

Sequence diagram

External trigger synchro

@startuml
skinparam maxMessageSize 450
' To add a number by line
'autonumber

title "ExtTriggerSynchro in Cube 2"


' Fix order of each column
participant "User Application" as App
participant "HAL TIM" as Driver

group Initialization
App -[hidden]>Driver
App -> Driver : Configure TIM1, TIM2 time base
Driver -> App : HAL_OK
end

group Configuration of master and salve timer
App -> Driver : Configure TIM1 as slave for external trigger  and master for TIM2.
Driver --> App : HAL_OK
App -> Driver : Configure TIM2 as slave for TIM1.
Driver --> App : HAL_OK

App -> App : CH1, CH2 GPIO AF config

end

group Start TIM1 and TIM2

App -> Driver : <b>HAL_TIM_IC_Start</b>(&htim<b><font color=red>1</b>, TIM_CHANNEL_2)
App -> Driver : <b>HAL_TIM_OC_Start</b>(&htim<b><font color=red>1</b>, TIM_CHANNEL_1)
Driver --> App : HAL_OK

App -> Driver : <b>HAL_TIM_OC_Start</b>(&htim<b><font color=green>2</b>, TIM_CHANNEL_1)
Driver --> App : HAL_OK
end
@enduml

Code snippet

HAL1

HAL2

/* Declaration of tim handle */
TIM_HandleTypeDef htim1, htim2;
TIM_SlaveConfigTypeDef sSlaveConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};

/* Ensure that all required peripherals
(TIM(basic configurations),
 GPIO etc.) are configured properly
 before starting the timers using STM32CubeMX2 */
.............

 /* Configure the slave mode for TIM1*/
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_GATED;
  sSlaveConfig.InputTrigger = TIM_TS_TI2FP2;
  sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_RISING;
  sSlaveConfig.TriggerFilter = 0;
  HAL_TIM_SlaveConfigSynchro(&htim1, &sSlaveConfig);

  /* Configure the master mode for TIM1*/
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_ENABLE;
  sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_ENABLE;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
  HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig);

  /* Configure the output channel generated by TIM1 to trigger TIM2*/
  sConfigOC.OCMode = TIM_OCMODE_TOGGLE;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
  HAL_TIM_OC_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);

  /* Configure the slave mode  for TIM2*/
  SlaveConfig.SlaveMode = TIM_SLAVEMODE_GATED;
  SlaveConfig.InputTrigger = TIM_TS_ITR2;
  HAL_TIM_SlaveConfigSynchro(&htim2, &sSlaveConfig)

  /* Configure the master mode for TIM2*/
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig);

  /* Configure the output channel generated by TIM2*/
  sConfigOC.OCMode = TIM_OCMODE_TOGGLE;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);


  /* Start the timers */
  HAL_TIM_IC_Start(&htim1, TIM_CHANNEL_2);
  HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_1);
  HAL_TIM_OC_Start(&htim2, TIM_CHANNEL_1);
 /* Declaration of the tim handle */
 hal_tim_handle_t htim, htim2;
 hal_tim_config_t tim_config;
 hal_tim_oc_compare_unit_config_t tim_oc_compare_unit_config;
 hal_tim_oc_channel_config_t tim_oc_channel_config;
 hal_tim_slave_config_t slave_config;
 hal_tim_ic_capture_unit_config_t ic_compare_unit_config;
 hal_tim_ic_channel_config_t ic_config;


  /* Ensure that all required peripherals
  (TIM(basic configurations),
   GPIO etc.) are configured properly
   before starting the timers using STM32CubeMX2 */
  .............
 .............

/* Configure the CH2 used to capture the external trigger*/
 ic_config.source    = HAL_TIM_INPUT_TIM1_TI2_GPIO;
 ic_config.polarity  = HAL_TIM_IC_RISING;
 ic_config.filter    = HAL_TIM_FDIV1;
 HAL_TIM_IC_SetConfigChannel(&htim1, HAL_TIM_CHANNEL_2, &ic_config);

 ic_compare_unit_config.source     = HAL_TIM_IC_DIRECT;
 ic_compare_unit_config.prescaler  = HAL_TIM_IC_DIV1;
 HAL_TIM_IC_SetConfigCaptureUnit(&htim1, HAL_TIM_IC_CAPTURE_UNIT_2,
                                 &ic_compare_unit_config);

 /* Configure the slave mode for TIM1*/
 slave_config.mode     = HAL_TIM_SLAVE_GATED;
 slave_config.trigger  = HAL_TIM_TRIG_TI2FP2;
 HAL_TIM_SetSynchroSlave(&htim1, &slave_config);

 /* Configure Master mode */
 HAL_TIM_SetTriggerOutput(&htim1, HAL_TIM_TRGO_ENABLE);
 HAL_TIM_EnableMasterSlaveMode(&htim1);

 /* Configure the output channel generated by TIM1 to trigger TIM2*/
 tim_oc_channel_config.polarity = HAL_TIM_OC_LOW;
 tim_oc_channel_config.idle_state = HAL_TIM_OC_IDLE_STATE_RESET;
 HAL_TIM_OC_SetConfigChannel(&htim1, HAL_TIM_CHANNEL_1,
                             &tim_oc_channel_config);

 tim_oc_compare_unit_config.mode = HAL_TIM_OC_PWM1;
 tim_oc_compare_unit_config.pulse = PULSE_VALUE;
 HAL_TIM_OC_SetConfigCompareUnit(&htim1, HAL_TIM_OC_COMPARE_UNIT_1,
                                 &tim_oc_compare_unit_config);

 /* Configure the slave mode for TIM2*/
 slave_config.mode     = HAL_TIM_SLAVE_GATED;
 slave_config.trigger  = HAL_TIM_TRIG_ITR2;
 HAL_TIM_SetSynchroSlave(&htim2, &slave_config);

 /* Configure the output channel generated by TIM2*/
 tim_oc_channel_config.polarity = HAL_TIM_OC_LOW;
 tim_oc_channel_config.idle_state = HAL_TIM_OC_IDLE_STATE_RESET;
 HAL_TIM_OC_SetConfigChannel(&htim2, HAL_TIM_CHANNEL_1,
                             &tim_oc_channel_config);

 tim_oc_compare_unit_config.mode = HAL_TIM_OC_PWM1;
 tim_oc_compare_unit_config.pulse = PULSE_VALUE;
 HAL_TIM_OC_SetConfigCompareUnit(&htim2, HAL_TIM_OC_COMPARE_UNIT_1,
                                 &tim_oc_compare_unit_config);

 /* Start the timers */
 HAL_TIM_IC_StartChannel(&htim1, HAL_TIM_CHANNEL_2);
 HAL_TIM_OC_StartChannel(&htim1, HAL_TIM_CHANNEL_1);
 HAL_TIM_OC_StartChannel(&htim2, HAL_TIM_CHANNEL_1);
 HAL_TIM_Start(&htim1);
 HAL_TIM_Start(&htim2);

Key changes

  1. HAL2 uses dedicated configuration APIs for slave synchronization, master mode, and output channel configuration.

  2. Timer start in HAL2 uses per-channel start APIs and requires explicit timer start using HAL_TIM_Start().